package com.mybatis.lo.builder;

import com.mybatis.lo.config.Configuration;
import com.mybatis.lo.sqlnode.IfSqlNode;
import com.mybatis.lo.sqlnode.MixedSqlNode;
import com.mybatis.lo.sqlnode.SqlNode;
import com.mybatis.lo.sqlnode.StaticTextSqlNode;
import com.mybatis.lo.sqlnode.TextSqlNode;
import com.mybatis.lo.sqlnode.WhereSqlNode;
import com.mybatis.lo.sqlsource.DynamicSqlSource;
import com.mybatis.lo.sqlsource.RawSqlSource;
import com.mybatis.lo.sqlsource.SqlSource;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.Text;

import java.util.ArrayList;
import java.util.List;

/**
 * 解析某个`<select|insert|update|...>`Statement内容脚本的构建器
 * @author zhangbh
 * 2023-06-16 07:33
 **/
public class XMLScriptBuilder extends BaseBuilder {

    /**
     * 是否是动态脚本（带动态标签或者${}）
     */
    private boolean isDynamic;

    public XMLScriptBuilder(Configuration configuration) {
        super(configuration);
    }

    public SqlSource loadScriptNode(Element element) {
        SqlNode mixedSqlNode = loadSqlNodes(element);
        return isDynamic ? new DynamicSqlSource(mixedSqlNode) : new RawSqlSource(mixedSqlNode);
    }

    private SqlNode loadSqlNodes(Element element) {
        SqlNode mixedSqlNode = null;
        List<SqlNode> nodes = new ArrayList<>();
        int nodeCount = element.nodeCount();
        // 遍历所有内容
        for (int i = 0; i < nodeCount; i++) {
            Node node = element.node(i);
            // 判断节点是Text 或者是Element元素
            if (node instanceof Text) {
                String text = node.getText().trim();
                if (isNullOrEmpty(text)) {
                    continue;
                }
                // 判断是否存在${符号
                boolean contains = text.contains("${");
                if (contains) {
                    isDynamic = true;
                    nodes.add(new TextSqlNode(text));
                } else {
                    nodes.add(new StaticTextSqlNode(text));
                }
            } else if (node instanceof Element) {
                isDynamic = true;
                // todo 这边也可以通过策略模式 匹配标签名进行处理
                // 判断一下if、where标签
                if (node.getName().equals("if")) {
                    String test = ((Element) node).attributeValue("test");
                    nodes.add(new IfSqlNode(test, loadSqlNodes((Element) node)));
                } else if (node.getName().equals("where")) {

                    nodes.add(new WhereSqlNode(loadSqlNodes((Element) node)));
                } else {
                    // todo 其他标签也没有处理
                    System.out.println("解析到未处理标签");
                }
            } else {
                // todo 其他类型的节点信息，没去处理
            }
        }
        mixedSqlNode = new MixedSqlNode(nodes);

        return mixedSqlNode;
    }
}
